package com.sskj.motherboard.handler.strategy;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.sskj.common.constant.RabbitMQConstant;
import com.sskj.common.dto.DeviceQueueMessage;
import com.sskj.common.dto.motherboard.RegisterMessage;
import com.sskj.common.enums.DeviceMessageTypeEnum;
import com.sskj.common.util.StrUtil;
import com.sskj.motherboard.constant.ChannelAttributesConstant;
import com.sskj.motherboard.server.ClientManager;
import com.sskj.motherboard.vo.FrameMessage;
import io.netty.channel.ChannelHandlerContext;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.nio.charset.StandardCharsets;
import java.util.Arrays;

@Slf4j
@Component
public class RegisterHandler implements IFrameMessageHandlerStrategy {

    @Autowired
    private RabbitTemplate rabbitTemplate;

    @Autowired
    private ObjectMapper objectMapper;

    @Override
    public void handle(ChannelHandlerContext channelHandlerContext, FrameMessage frameMessage) {
        if (frameMessage.getData() == null || frameMessage.getData().length < 74) {
            throw new IllegalArgumentException("Data length must be at least 74 bytes");
        }
        log.info("数据帧具体内容: {}", StrUtil.toHexStr(frameMessage.getData()));
        byte[] nameBytes = new byte[32];
        byte[] codeBytes = new byte[32];
        byte[] versionBytes = new byte[4];
        byte[] reserved = new byte[4];

        System.arraycopy(frameMessage.getData(), 0, nameBytes, 0,32);
        System.arraycopy(frameMessage.getData(), 32, codeBytes, 0,32);
        System.arraycopy(frameMessage.getData(), 64, versionBytes, 0, 4);
        int deviceType = frameMessage.getData()[68] & 0xFF;
        int channelCount = frameMessage.getData()[69] & 0xFF;
        System.arraycopy(frameMessage.getData(), 70, reserved, 0, 4);

        String deviceName = trimString(new String(nameBytes, StandardCharsets.UTF_8));
        String deviceCode = trimString(new String(codeBytes, StandardCharsets.UTF_8));
        String deviceVersion = parseVersion(versionBytes);

        RegisterMessage registerMessage = new RegisterMessage();
        registerMessage.setCode(deviceCode);
        registerMessage.setName(deviceName);
        registerMessage.setType(deviceType);
        registerMessage.setChannelNumbers(channelCount);
        registerMessage.setVersion(deviceVersion);
        registerMessage.setReserved(reserved);

        // 客户端连接和设备绑定
        channelHandlerContext.channel().attr(ChannelAttributesConstant.DEVICE_ID).set(deviceCode);
        ClientManager.register(deviceCode, channelHandlerContext.channel());

        // 推送到消息队列
        try {
            String payload = objectMapper.writeValueAsString(registerMessage);
            DeviceQueueMessage deviceQueueMessage = new DeviceQueueMessage();
            deviceQueueMessage.setType(DeviceMessageTypeEnum.REGISTER.getType());
            deviceQueueMessage.setPayload(payload);

            String queueMessage = objectMapper.writeValueAsString(deviceQueueMessage);
            rabbitTemplate.convertAndSend(RabbitMQConstant.IOT_EXCHANGE, RabbitMQConstant.IOT_ROUTEING_KEY, queueMessage);
        } catch (JsonProcessingException e) {
            log.error("序列化异常。异常信息：{}", e.getMessage());
        }

        // 回复注册成功
        FrameMessage replyFrameMessage = new FrameMessage();
        replyFrameMessage.setCommandCode((byte) 0x02);
        replyFrameMessage.setCommandType((byte) 0x81);

        // 组装帧数据正文内容
        byte[] sessionIdBytes = deviceCode.getBytes(StandardCharsets.UTF_8);
        byte[] data = new byte[sessionIdBytes.length + 1];
        data[0] = (byte)1;
        System.arraycopy(sessionIdBytes, 0, data, 1, sessionIdBytes.length);
        replyFrameMessage.setData(data);

        channelHandlerContext.channel().writeAndFlush(replyFrameMessage);
    }

    // 去除字符串中的空字节和空格
    private String trimString(String str) {
        return str.replaceAll("\0", "").trim();
    }

    // 解析版本号
    private String parseVersion(byte[] bytes) {
        if (bytes.length == 4) {
            StringBuilder sb = new StringBuilder();
            for (int i = 3; i >= 0; i--) {
                int value = bytes[i] & 0xFF;
                sb.append(value);
            }

            return sb.toString();
        }
        return "";
    }
}
